import re
import math
from inc import *
from django.db.models import Q

def Rad(x):
  return math.radians(x)

def BuildQueryReg(sstr,spath):
  reg = re.compile("[a-zA-Z]+")
  itms = reg.finditer(sstr)
  reg_str = [] 
  for t in itms:
    reg_str.append(t.group()) 
  if reg_str:
    reg_exp = "("+"|".join(reg_str)+")" 
    return "(?im)" + reg_exp
  else:
    return None

def BuildDataQueryReg(sstr,key):
  reg = re.compile("[\w\d-]+")
  itms = reg.finditer(sstr)
  reg_str = []
  for t in itms:
    reg_str.append(t.group())
  if reg_str:
    reg_exp = "("+"|".join(reg_str)+")" 
    return "(?im)" + key + "\s*=\s*\"[^\"]*" + reg_exp + "[^\"]*\""
  else:
    return None

def ComputeDistance(latlong1,latlong2):
  r = 6371
  dlat = Rad(latlong1['lat'] - latlong2['lat'])
  dlong = Rad(latlong1['long'] - latlong2['long'])
  a = math.sin(dlat/2)*math.sin(dlat/2) + math.cos(Rad(latlong1['lat']))*math.cos(Rad(latlong2['lat']))*math.sin(dlong/2)*math.sin(dlong/2)
  c = 2*math.atan2(math.sqrt(a),math.sqrt(1-a));
  return r*c 

def FiltByDistance(services,llbase,radius):
  def compare(a, b):
    aLlinc = {'lat':float(a.latitude)/1000000,'long':float(a.longitude)/1000000}
    aDis = ComputeDistance(llbase,aLlinc)
    bLlinc = {'lat':float(b.latitude)/1000000,'long':float(b.longitude)/1000000}
    bDis = ComputeDistance(llbase,bLlinc)
    return cmp(aDis, bDis)
  results = []
  VIPs = []
  nonVIPs = []
  if llbase['lat'] and llbase['long'] and radius:
    for service in services:
      llinc = {'lat':float(service.latitude)/1000000,'long':float(service.longitude)/1000000}
      dis = ComputeDistance(llbase,llinc)
      if(dis < radius):
        if service.grade >= 4: 
          VIPs.append(service)
        else:
          nonVIPs.append(service)
  else:
    for service in services:
      results.append(service)
  VIPs.sort(compare)
  nonVIPs.sort(compare)
  VIPs.extend(nonVIPs)
  if len(results) == 0:
    results = VIPs
  return results

def GetServices(filter_dict):
  try:
    services = ServiceCore.objects
    distances = {}
    results = []
    if(not filter_dict.has_key('TARGET')):
      return None
    #elif (filter_dict['TARGET'] == 'general' or filter_dict['TARGET'] == 'address'):
    elif (filter_dict['TARGET'] == 'general'):
      '''
      if(filter_dict.has_key('MAIN')):
        sstr = filter_dict['MAIN']
        dsp_reg = BuildQueryReg(sstr,None)
        if(dsp_reg):
          query = Q(description__regex = dsp_reg) | Q(type__regex = dsp_reg) | Q(name__regex = dsp_reg) | Q(address__regex = dsp_reg) | Q(nation__regex = dsp_reg)
          services = services.filter(query)
      '''
      if(filter_dict.has_key('STYPE')):
        if(filter_dict['STYPE'] != 'All'):
          types = filter_dict['STYPE'].split(',')
          regex = "|".join(types);
          if (regex != 'all'):
            services = services.filter(type__regex=regex)
      if(filter_dict.has_key('NATION')):
        nations = filter_dict['NATION'].split(',')
        regex = "|".join(nations);
        services = services.filter(nation__regex=regex)
      if(filter_dict.has_key('LOCAL')):
        locals = filter_dict['LOCAL'].split(',')
        regex = "|".join(locals);
        if (regex != 'all'):
          services = services.filter(local__regex=regex)
      if(filter_dict.has_key('PRICE') 
        and filter_dict['PRICE'].has_key('MAX')
        and filter_dict['PRICE'].has_key('MIN')): 
        services = services.filter(pricelow__gte = (int (filter_dict['PRICE']['MIN'])))
        services = services.filter(pricehigh__lte = (int (filter_dict['PRICE']['MAX'])))
      if(filter_dict.has_key('LOCATION') and filter_dict.has_key('RADIUS')):
        llbase = {'lat':float(filter_dict['LOCATION']['x']),
                 'long':float(filter_dict['LOCATION']['y'])}
        results = FiltByDistance(services,llbase,int(filter_dict['RADIUS']))
      else:
        for service in services:
          results.append(service)
      return results
    elif (filter_dict['TARGET'] == 'item'):
      if(filter_dict.has_key('LOCAL')):
        locals = filter_dict['LOCAL'].split(',')
        regex = "|".join(locals);
        if (regex != 'all'):
          services = services.filter(local__regex=regex)
      if(filter_dict.has_key('LOCATION') and filter_dict.has_key('RADIUS')):
        llbase = {'lat':float(filter_dict['LOCATION']['x']),
                 'long':float(filter_dict['LOCATION']['y'])}
        results = FiltByDistance(services,llbase,int(filter_dict['RADIUS']))
      else:
        for service in services:
          results.append(service)
      return results
    else:
      return None
  except:
    return None
